import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;

public class Main extends JFrame implements ActionListener {
    // 定义两个面板
    private JPanel north,center;
    // 文本框 用于显示计算结果
    private JTextField field;
    // 定义按钮
    private JButton[] btns;
    // 按钮文字数组
    private String[] str;
    // 计算引擎
    private ScriptEngine engine;//计算引擎
    private Timer timeUpdateTimer;
    private boolean timeDisplayActive = false;
    private AbstractButton historyText;

    // 构造函数
    public Main(){
        // 构造函数
        // 设置窗口标题
        setTitle("计算器");

        // 设置窗口大小 宽 高
        setSize(700,700);

        // 关闭窗口时结束程序
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // 设置窗口的位置
        setLocation((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth() - this.getWidth())/2,
                (int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight() - this.getHeight())/2);

        // 初始化窗口
        initComponent();

        // 设置窗口可见
        setVisible(true);
    }

    // 初始化窗口的方法
    // 无参、无返回值
    private void initComponent() {
        // 窗口中添加内容
        // 创建面板
        ScriptEngineManager manager = new ScriptEngineManager();
        engine = manager.getEngineByName("JavaScript");

        north = new JPanel();
        center = new JPanel();
        // 创建文本框
        field = new JTextField();
        // 设置文本框属性
        // field.setColumns();
        // 设置宽高属性
        field.setPreferredSize(new Dimension(700,150));
        // 输入框禁止编辑
        field.setEditable(false);
        // 设置一个字体格式
        Font font = new Font("SansSerif",Font.BOLD,25);
        // 设置字体、加粗、大小
        field.setFont(font);
        // 以数组的形式声明的按钮字符
        str = new String[]{//增加计算机更多计算功能
                "sin","cos","tan","J",
                "7","8","9","+",
                "4","5","6","-",
                "1","2","3","×",
                "0",".","=","÷",
                "C","B","T","S",
                "(",")",
        };
        // 创建按钮
        btns = new JButton[str.length];
        for (int i = 0; i < btns.length; i++){
            btns[i] = new JButton(str[i]);
            btns[i].setFont(new Font("SansSerif",Font.BOLD,25));
        };

        // 设置布局
        north.setLayout(new BorderLayout());
        // 设置按钮面板的布局
        center.setLayout(new GridLayout(6,4));
        // 将文本框添加到上面的面板
        north.add(field);
        // 将btn添加到center面板
        for (int i = 0; i < btns.length; i++){
            center.add(btns[i]);
        }
        // 将面板添加到窗口中
        this.add(north,BorderLayout.NORTH);
        this.add(center);
        // 给按键添加事件监听
        for (int i = 0; i < btns.length; i++){
            btns[i].addActionListener(this);
        }

    }
    public void showtime(boolean isShow) {
        // 如果需要显示时间
        if (isShow) {
            // 如果时间显示未激活
            if (!timeDisplayActive) {
                // 激活时间显示
                timeDisplayActive = true;
                // 如果时间更新定时器为空或者未运行
                if (timeUpdateTimer == null || !timeUpdateTimer.isRunning()) {
                    // 创建一个新的时间更新定时器，每隔1秒执行一次更新当前时间的操作
                    timeUpdateTimer = new Timer(1000, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            // 更新当前时间
                            updateCurrentTime();
                        }
                    });
                    // 启动时间更新定时器
                    timeUpdateTimer.start();
                }
            }
            // 如果不需要显示时间
        } else {
            // 如果时间显示已激活
            if (timeDisplayActive) {
                // 取消激活时间显示
                timeDisplayActive = false;
                // 如果时间更新定时器不为空且正在运行
                if (timeUpdateTimer != null && timeUpdateTimer.isRunning()) {
                    // 停止时间更新定时器
                    timeUpdateTimer.stop();
                }
                // 清空显示字段
                field.setText(" ");
            }
        }
    }

    private void updateCurrentTime() {
        // 创建一个 SimpleDateFormat 对象，用于格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将当前日期时间转换为指定格式的字符串，并设置到 field 组件的文本上
        field.setText(sdf.format(new java.util.Date()));
    }
    //括号优先运算
    public void calculate(String leftStr){
        // 获取输入框中的内容
        //这段代码定义了一个名为 calculate 的方法，它用于处理括号优先的运算。这个方法的目的是递归地计算包含括号的表达式。下面是代码的逐行解释：
        //
        //java
        String str = field.getText();
        //这个方法接受一个字符串参数 leftStr，这个参数用于存储括号外的表达式部分。
        System.out.println(str);
        //打印出当前的字符串，用于调试目的。
        if (str.contains("(")){//检查字符串 str 是否包含左括号 (。如果包含，说明表达式中可能有括号需要优先计算。
            int index = str.indexOf("(");//找到左括号在字符串中的索引位置。
            leftStr = str.substring(0, index);//将括号左边的表达式部分（不包括括号本身）赋值给 leftStr。
            String rightStr = str.substring(index+1,str.length()-1);//从左括号的下一个字符开始，到字符串的倒数第二个字符结束，提取括号内的表达式部分。
            calculate(leftStr);
            calculate(rightStr);//递归调用 calculate 方法，计算括号外的表达式。


            field.setText(leftStr + "(" + rightStr + ")");//括号外的表达式和括号内的表达式合并，并将结果设置回文本框 field。
        }else{
            try {
                Double result = (Double) engine.eval(str);//使用 ScriptEngine 对象 engine 来计算字符串 str 表示的表达式，并将结果转换为 Double 类型。
                field.setText(result+"");
            } catch (ScriptException e) {
                e.printStackTrace();
            }
        }
    }
    //历史计算记录功能
    public void showHistory(String text){  
        if(text.equals("J")){
            // 显示历史记录
            // 获取历史记录
          
            String history = historyText.getText();
            // 显示历史记录
            field.setText(history);
        }else if(text.equals("S")){
            // 显示当前时间
            showtime(true);
        }else{
            // 显示当前时间
            showtime(false);
            // 将按键上的文字显示到输入框
            field.setText(field.getText() + text);
        }
    }

    // 将按键上的文字显示到输入框
    public void showBtnText(String text){
        // System.out.println(text);

        // 判断text是不是数字
        // 注释掉的正则表达式检测text是否为数字
        // 用正则表达式检测text是不是数字
        //        Boolean isNum = text.matches("\\d");
        //        if (isNum){
        //            // 如果是数字，就拼接到字符串上
        //            // 注释掉的数字处理逻辑
        //            // 输入框上已有的文字
        //            String oldText = field.getText();
        //            field.setText(oldText + text);
        //        }else{
        // 如果不是数字，就特殊处理
        // 如果是运算符怎么办?
        if("C".equals(text)){
            System.out.println("C");
            // 清除输入框
            // 注释：清除输入框
            field.setText("");
        }else if("B".equals(text)){
            System.out.println("B");
            // 删除最后一位
            // 注释：删除输入框中的最后一位字符
            // 当前文本框的内容
            // String
            if(field.getText().length()>0){
                // 先获取输入框的内容，然后截取掉最后一位，将截取后的内容重新设置到输入框
                // 注释：处理删除最后一位字符的逻辑
                field.setText(field.getText().substring(0, field.getText().length()-1));
            }
        }else if("T".equals(text)){
            //            one_time_play("sound/时间.wav");
            //            System.out.println( "T");
            //            //输入框中显示时间
            //            updateCurrentTime();

            //            System.out.println("T");
            // 显示时间，显示到输入框中，每秒刷新一次，刷新一次，显示时间
            // 注释：显示时间到输入框中
            showtime(true);

        }else if("S".equals(text)){
            System.out.println( "S");
            //关闭时间显示
            // 注释：关闭时间显示
            //            field.setText("");
            showtime(false);
        }else if("sin".equals(text)){
            System.out.println("sin");


        }else if ("cos".equals(text)){
            // 注释：处理cos的情况
            System.out.println("cos");

        }else if ("tan".equals(text)){
            // 注释：处理tan的情况
            System.out.println("tan");

        }else if ("e".equals(text)){
            // 注释：处理e的情况
            System.out.println("e");

        }else if("=".equals(text)){
            System.out.println("=");

            try{
                // 计算输入框中的内容
                // 注释：计算输入框中的内容
                String txt = field.getText();
                System.out.println(txt);
                txt= txt.replaceAll("×", "*").replaceAll("÷", "/");
                System.out.println(txt);
                Object o=engine.eval(txt);
                //将o转换为字符串
                // 注释：将计算结果转换为字符串并显示在输入框中
                field.setText(o+"");
            }catch (Exception e){
                e.printStackTrace();

            }

            // 注释：已注释的停止显示时间的逻辑
            // 写一个timmer类，停止显示时间
            //                String txt = field.getText();
            //                System.out.println(txt);
            //
            //                Object o=engine.eval(txt);
        }
        // 如果是运算符
        // 保留已输入的数字~
        // 注释：运算符的处理逻辑
        // String oldNum = field.getText();
        // System.out.println(oldNum);
        // 清空输入区
        // field.setText(text);
        else{
            // 数字、小数点 和 运算符
            // 注释：将其他字符（如数字、小数点）拼接到输入框中
            String oldText = field.getText();
            field.setText(oldText + text);
        }

    }

    // 重写方法
    @Override
    public void actionPerformed(ActionEvent e) {
        // 判断触发事件的源对象
        // 输出捕获到的 Action
        // System.out.println(e.getSource());
        Object source = e.getSource();
        // 判断源对象是否是 JButton 的实例
        if (source instanceof JButton){
            // 强制转换为 JButton 类型
            JButton btn = (JButton) source;
            // 获取按键的文字
            String text = btn.getText();
            // 输出按键的文字（可选）
            // System.out.println(text);

            // 调用 showBtnText 方法处理按键文字
            this.showBtnText(text);
        }
    }


    public static void main(String[] args) {
        // 注释掉打印"hello,world"的代码
        // System.out.println("hello,world");

        // 创建一个实例
        // 创建一个 Main 类的实例
        new Main();
    }

}